package managedbean;

import entity.Client;
import entity.IndicativeProductPrice;
import entity.Quotation;
import entity.QuotationItem;
import java.sql.Timestamp;
import java.util.Collection;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ActionEvent;
import session.IndicativeProductPriceManager;
import session.QuotationManager;
import java.util.ArrayList;

/**
 *
 * @author Samuel
 */
@ManagedBean
@SessionScoped
public class QuotationBean {

    @EJB
    private QuotationManager quotationManager;
    @EJB
    private IndicativeProductPriceManager ippm;
    private Long quotationId;
    private String productName;
    private Integer numOfProduct;
    private Double productPrice;
    private Integer daysValid;
    private Integer indicativeLeadTime; //in days
    private Timestamp dateTime;
    private Collection<QuotationItem> quotationItems;
    private Collection<Quotation> quotationList;
    private Collection<IndicativeProductPrice> productsList;
    private String businessType;
    private Collection<Client> clients;
    private Boolean dealingWithSalesLead;
    private Boolean dealingWithCustomer;
    private Long clientId;
    private Long indicativeProductPriceId;
    private String outcome; // for feeding back outcome of functions
    private String status;
    private Boolean needDaysValid;
    private Boolean needLeadTime;
    private Long quotationItemId;
    private Double totalPrice;
    private Quotation quotation;

    /** Creates a new instance of QuotationBean */
    public QuotationBean() {
        totalPrice = 0.0;
    }

    public void retrieveClients(ActionEvent event) {
        clients = quotationManager.getClients();
    }

    public void retrieveProductsList(String businessType) {
        productsList = ippm.getProductsList(businessType);
    }

    public void retrieveAllProductsList(ActionEvent event) {
        productsList = ippm.getProductsList();
    }

    public void addIndicativeProductPrice(ActionEvent event) {
        Boolean alreadyExisted = false;

        for (Object o : productsList) {
            IndicativeProductPrice temp = (IndicativeProductPrice) o;
            if ((temp.getProductName().equals(productName))
                    && (temp.getBusinessType().equals(businessType))) {
                setOutcome("ERROR:A similar entry [" + productName + "-" + businessType + "]already existed in the indicative product price table. "
                        + "Please delete the original entry or add a different entry");
                alreadyExisted = true;
            }

        }
        if (alreadyExisted.equals(false)) {
            ippm.createIndicativeProductPrice(getProductName(), getBusinessType(), getProductPrice());
            setOutcome("Entry successfully added!");
        }

        resetAll();

    }

    public void deleteIndicativeProductPrice(ActionEvent event) {
        ippm.removeIndicativeProductPrice(indicativeProductPriceId);
        outcome = "Successful deletion of entry.";
        resetAll();
    }

    public void chooseIndicativeProductPrice(ActionEvent event) {
        for (Object o : productsList) {
            IndicativeProductPrice temp = (IndicativeProductPrice) o;
            if (temp.getId().equals(indicativeProductPriceId)) {
                productName = temp.getProductName();
                productPrice = temp.getPrice();
                businessType = temp.getBusinessType();
            }
        }
    }

    public void editIndicativeProductPrice(ActionEvent event) {
        Boolean alreadyExisted = false;

        for (Object o : productsList) {
            IndicativeProductPrice temp = (IndicativeProductPrice) o;
            if ((temp.getProductName().equals(productName))
                    && (temp.getBusinessType().equals(businessType))
                    && !(temp.getId().equals(indicativeProductPriceId))) {
                setOutcome("ERROR:A similar entry [" + productName + "-" + businessType + "]already existed in the indicative product price table. "
                        + "Please delete the original entry or change edit to entry.");
                alreadyExisted = true;
            }

        }
        if (alreadyExisted.equals(false)) {
            ippm.editIndicativeProductPrice(indicativeProductPriceId, productName, businessType, productPrice);
            outcome = "Edit to indicative product price is successful.Click button to return to menu.";
        }
        resetAll();
    }

    public void addNewQuotation(ActionEvent event) {
        Client c = new Client();
        c = quotationManager.getClient(clientId);
        this.setBusinessType(c.getBusinessType());

        quotationManager.createQuotation(daysValid);
        quotationManager.getQuotation().setNeedDaysValid(false);

        this.setDateTime(quotationManager.getQuotation().getDateTime());

        retrieveProductsList(businessType);
    }

    public void clientAskForQuotation(ActionEvent event) {

        Client c = new Client();

        //COMMENT OFF UNTIL INTEGRATION, UNTESTED CODE
        //String username  = (String) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("user");
        // c = quotationManager.getClient(username);

        //to be removed/replaced by part above during INTEGRATION , need to have a client in database with id=43 for this to work
        c = quotationManager.getClient(43L);


        clientId = c.getId();
        this.setBusinessType(c.getBusinessType());
        quotationManager.createQuotation();
        quotationManager.getQuotation().setNeedDaysValid(Boolean.TRUE);
        this.setDateTime(quotationManager.getQuotation().getDateTime());
        retrieveProductsList(businessType);


    }

    public void chooseQuotation(ActionEvent event) {
        for (Object o : quotationList) {
            Quotation temp = (Quotation) o;
            if (temp.getId().equals(quotationId)) {
                indicativeLeadTime = temp.getIndicativeLeadTime();
                daysValid = temp.getDaysValid();
                businessType = temp.getClient().getBusinessType();
                status = temp.getStatus();
                clientId = temp.getClient().getId();
                needDaysValid = temp.getNeedDaysValid();
                needLeadTime = temp.getNeedLeadTime();

            }
        }
        quotationItems = quotationManager.getQuotationItems(quotationId);
        //clients = quotationManager.getClients();
    }

    public void editQuotation(ActionEvent event) {
        if ((daysValid == null) && (indicativeLeadTime == null)) {
            needDaysValid = Boolean.TRUE;
            needLeadTime = Boolean.TRUE;
            status = "Waiting for Days of Validity and Indicative Lead Time";
        } else if (daysValid == null) {
            needDaysValid = Boolean.TRUE;
            needLeadTime = Boolean.FALSE;
            status = "Waiting for Days of Validity";
        } else if (indicativeLeadTime == null) {
            needLeadTime = Boolean.TRUE;
            needDaysValid = Boolean.FALSE;
            status = "Waiting for Indicative Lead Time";
        }

        quotationManager.editQuotation(quotationId, indicativeLeadTime, daysValid, status, needDaysValid, needLeadTime, clientId);
        outcome = "Quotation successfully edited.";
        resetAll();
    }

    public void inputLeadTime(ActionEvent event) {
        quotationManager.addLeadTimeToQuotation(quotationId, indicativeLeadTime);
        outcome = "Edit is successful. Click button to return to menu.";
        resetAll();
    }

    public void inputDaysValid(ActionEvent event) {
        quotationManager.addDaysValidToQuotation(quotationId, daysValid);
        outcome = "Edit is successful. Click button to return to menu.";
        resetAll();
    }

    public void addNewQuotationItem(ActionEvent event) {

        for (Object o : productsList) {
            IndicativeProductPrice temp = (IndicativeProductPrice) o;
            if (temp.getId().equals(indicativeProductPriceId)) {
                productName = temp.getProductName();
                productPrice = temp.getPrice();
            }
        }
        quotationManager.addQuotationItem(productName, numOfProduct, productPrice);
        totalPrice = totalPrice + (productPrice * numOfProduct);
    }

    public void prepareAddItem(ActionEvent event) {
        retrieveProductsList(businessType);
        numOfProduct = null;
    }

    public void addItem(ActionEvent event) {
        for (Object o : productsList) {
            IndicativeProductPrice temp = (IndicativeProductPrice) o;
            if (temp.getId().equals(indicativeProductPriceId)) {
                productName = temp.getProductName();
                productPrice = temp.getPrice();
            }
        }
        quotationManager.editAddQuotationItem(quotationId, productName, numOfProduct, productPrice);
        indicativeLeadTime = null;

    }

    public void getItems(ActionEvent event) {
        quotationItems = quotationManager.getQuotationItems(quotationId);
    }

    public void deleteItem(ActionEvent event) {
        quotationManager.deleteQuotationItem(quotationId, quotationItemId);
        quotationItems = quotationManager.getQuotationItems();
        indicativeLeadTime = null;
    }

    public void prepareEditItem(ActionEvent event) {
        numOfProduct = quotationManager.getQuotationItem(quotationItemId).getNumOfProduct();
    }

    public void editItem(ActionEvent event) {
        quotationManager.editQuotationItem(quotationItemId, numOfProduct);
        quotationItems = quotationManager.getQuotationItems(quotationId);
        indicativeLeadTime = null;
    }

    public void confirmNewQuotation(ActionEvent event) {
        // quotationManager.persistQuotation();

        quotationManager.getQuotation().setClient(quotationManager.getClient(clientId));

        if ((quotationManager.getQuotation().getNeedDaysValid().equals(Boolean.TRUE))
                && (quotationManager.getQuotation().getNeedLeadTime().equals(Boolean.TRUE))) {
            quotationManager.getQuotation().setStatus("Waiting for Days of Validity and Indicative Lead Time");
        } else if (quotationManager.getQuotation().getNeedLeadTime().equals(Boolean.TRUE)) {
            quotationManager.getQuotation().setStatus("Waiting for Indicative Lead Time");
        } else {
            quotationManager.getQuotation().setStatus("Waiting for Days of Validity");
        }
        quotationManager.persistQuotation();
        quotationId = quotationManager.getQuotation().getId();

    }

    public void getQuotationItems(ActionEvent event) {
        quotationItems = quotationManager.getQuotationItems();
    }

    public void getQuotationList(ActionEvent event) {
        quotationList = quotationManager.getQuotationList();
    }

    public void getClientQuotationList(ActionEvent event) {
        Client c = new Client();

        //COMMENT OFF UNTIL INTEGRATION, UNTESTED CODE
        //String username  = (String) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("user");
        // c = quotationManager.getClient(username);

        //to be removed/replaced by part above during INTEGRATION , need to have a client in database with id=43 for this to work
        c = quotationManager.getClient(43L);

        clientId = c.getId();
        quotationList = quotationManager.getQuotationList(clientId);
    }

    public void getNeedLeadTimeQuotationList(ActionEvent event) {
        quotationList = quotationManager.getNeedLeadTimeQuotationList();
    }

    public void getNeedValidityDaysQuotationList(ActionEvent event) {
        quotationList = quotationManager.getNeedValidityDaysQuotationList();
    }

    public void resetItem(ActionEvent event) {
        this.setProductName(null);
        this.setProductPrice(null);
        this.setNumOfProduct(null);
    }

    public void resetAfterConfirmQuotation(ActionEvent event) {
        resetAll();
    }

    public void viewQuotation(ActionEvent event) {
        quotation = quotationManager.getQuotation(quotationId);
    }

    public void resetAll() {

        productName = null;
        numOfProduct = null;
        productPrice = null;
        daysValid = null;
        indicativeLeadTime = null;
        dateTime = null;
        quotationItems = null;
        quotationList = null;
        productsList = null;
        businessType = null;
        clients = null;
        totalPrice = 0.0;
        dealingWithSalesLead = null;
        dealingWithCustomer = null;
        clientId = null;
        indicativeProductPriceId = null;
        //  outcome = null;

    }

    /**
     * @return the quotationManager
     */
    public QuotationManager getQuotationManager() {
        return quotationManager;
    }

    /**
     * @param quotationManager the quotationManager to set
     */
    public void setQuotationManager(QuotationManager quotationManager) {
        this.quotationManager = quotationManager;
    }

    /**
     * @return the quotationId
     */
    public Long getQuotationId() {
        return quotationId;
    }

    /**
     * @param quotationId the quotationId to set
     */
    public void setQuotationId(Long quotationId) {
        this.quotationId = quotationId;
    }

    /**
     * @return the productName
     */
    public String getProductName() {
        return productName;
    }

    /**
     * @param productName the productName to set
     */
    public void setProductName(String productName) {
        this.productName = productName;
    }

    /**
     * @return the numOfProduct
     */
    public Integer getNumOfProduct() {
        return numOfProduct;
    }

    /**
     * @param numOfProduct the numOfProduct to set
     */
    public void setNumOfProduct(Integer numOfProduct) {
        this.numOfProduct = numOfProduct;
    }

    /**
     * @return the daysValid
     */
    public Integer getDaysValid() {
        return daysValid;
    }

    /**
     * @param daysValid the daysValid to set
     */
    public void setDaysValid(Integer daysValid) {
        this.daysValid = daysValid;
    }

    /**
     * @return the indicativeLeadTime
     */
    public Integer getIndicativeLeadTime() {
        return indicativeLeadTime;
    }

    /**
     * @param indicativeLeadTime the indicativeLeadTime to set
     */
    public void setIndicativeLeadTime(Integer indicativeLeadTime) {
        this.indicativeLeadTime = indicativeLeadTime;
    }

    /**
     * @return the dateTime
     */
    public Timestamp getDateTime() {
        return dateTime;
    }

    /**
     * @param dateTime the dateTime to set
     */
    public void setDateTime(Timestamp dateTime) {
        this.dateTime = dateTime;
    }

    /**
     * @return the quotationItems
     */
    public Collection<QuotationItem> getQuotationItems() {
        return quotationItems;
    }

    /**
     * @param quotationItems the quotationItems to set
     */
    public void setQuotationItems(Collection<QuotationItem> quotationItems) {
        this.quotationItems = quotationItems;
    }

    /**
     * @return the quotationList
     */
    public Collection<Quotation> getQuotationList() {
        return quotationList;
    }

    /**
     * @param quotationList the quotationList to set
     */
    public void setQuotationList(Collection<Quotation> quotationList) {
        this.quotationList = quotationList;
    }

    /**
     * @return the productsList
     */
    public Collection<IndicativeProductPrice> getProductsList() {
        return productsList;
    }

    /**
     * @param productsList the productsList to set
     */
    public void setProductsList(Collection<IndicativeProductPrice> productsList) {
        this.productsList = productsList;
    }

    /**
     * @return the businessType
     */
    public String getBusinessType() {
        return businessType;
    }

    /**
     * @param businessType the businessType to set
     */
    public void setBusinessType(String businessType) {
        this.businessType = businessType;
    }

    /**
     * @return the dealingWithSalesLead
     */
    public Boolean getDealingWithSalesLead() {
        return dealingWithSalesLead;
    }

    /**
     * @param dealingWithSalesLead the dealingWithSalesLead to set
     */
    public void setDealingWithSalesLead(Boolean dealingWithSalesLead) {
        this.dealingWithSalesLead = dealingWithSalesLead;
    }

    /**
     * @return the dealingWithCustomer
     */
    public Boolean getDealingWithCustomer() {
        return dealingWithCustomer;
    }

    /**
     * @param dealingWithCustomer the dealingWithCustomer to set
     */
    public void setDealingWithCustomer(Boolean dealingWithCustomer) {
        this.dealingWithCustomer = dealingWithCustomer;
    }

    /**
     * @return the clientId
     */
    public Long getClientId() {
        return clientId;
    }

    /**
     * @param clientId the clientId to set
     */
    public void setClientId(Long clientId) {
        this.clientId = clientId;
    }

    /**
     * @return the indicativeProductPriceId
     */
    public Long getIndicativeProductPriceId() {
        return indicativeProductPriceId;
    }

    /**
     * @param indicativeProductPriceId the indicativeProductPriceId to set
     */
    public void setIndicativeProductPriceId(Long indicativeProductPriceId) {
        this.indicativeProductPriceId = indicativeProductPriceId;
    }

    /**
     * @return the outcome
     */
    public String getOutcome() {
        return outcome;
    }

    /**
     * @param outcome the outcome to set
     */
    public void setOutcome(String outcome) {
        this.outcome = outcome;
    }

    /**
     * @return the status
     */
    public String getStatus() {
        return status;
    }

    /**
     * @param status the status to set
     */
    public void setStatus(String status) {
        this.status = status;
    }

    /**
     * @return the needDaysValid
     */
    public Boolean getNeedDaysValid() {
        return needDaysValid;
    }

    /**
     * @param needDaysValid the needDaysValid to set
     */
    public void setNeedDaysValid(Boolean needDaysValid) {
        this.needDaysValid = needDaysValid;
    }

    /**
     * @return the needLeadTime
     */
    public Boolean getNeedLeadTime() {
        return needLeadTime;
    }

    /**
     * @param needLeadTime the needLeadTime to set
     */
    public void setNeedLeadTime(Boolean needLeadTime) {
        this.needLeadTime = needLeadTime;
    }

    /**
     * @return the quotationItemId
     */
    public Long getQuotationItemId() {
        return quotationItemId;
    }

    /**
     * @param quotationItemId the quotationItemId to set
     */
    public void setQuotationItemId(Long quotationItemId) {
        this.quotationItemId = quotationItemId;
    }

    /**
     * @return the clients
     */
    public Collection<Client> getClients() {
        return clients;
    }

    /**
     * @param clients the clients to set
     */
    public void setClients(Collection<Client> clients) {
        this.clients = clients;
    }

    /**
     * @return the productPrice
     */
    public Double getProductPrice() {
        return productPrice;
    }

    /**
     * @param productPrice the productPrice to set
     */
    public void setProductPrice(Double productPrice) {
        this.productPrice = productPrice;
    }

    /**
     * @return the totalPrice
     */
    public Double getTotalPrice() {
        return totalPrice;
    }

    /**
     * @param totalPrice the totalPrice to set
     */
    public void setTotalPrice(Double totalPrice) {
        this.totalPrice = totalPrice;
    }

    /**
     * @return the quotation
     */
    public Quotation getQuotation() {
        return quotation;
    }

    /**
     * @param quotation the quotation to set
     */
    public void setQuotation(Quotation quotation) {
        this.quotation = quotation;
    }
}
